import hashlib
import os
import random
import string
import time

from flask import Blueprint, request, jsonify, current_app
import requests

from flask_jwt_extended import create_access_token

from app.models.system import Tenant
from app.models.user import User
from app.core.extensions import db

login_bp = Blueprint('login', __name__)


def get_tenant_wechat_mp_config(tenant_id=None):
    """获取租户的微信小程序配置"""
    from app.services.tenant_config_service import TenantConfigService
    from app.models.tenant_config import ConfigTypes
    from flask import g, has_request_context

    if tenant_id is None:
        # 只有在请求上下文中才尝试从g获取tenant_id
        if has_request_context():
            tenant_id = getattr(g, 'tenant_id', 1)
        else:
            tenant_id = 1  # 默认使用租户1

    app_id = TenantConfigService.get_config(tenant_id, ConfigTypes.WECHAT_MP, 'app_id')
    app_secret = TenantConfigService.get_config(tenant_id, ConfigTypes.WECHAT_MP, 'app_secret')

    # 如果租户配置不存在，使用环境变量兜底
    if not app_id:
        app_id = os.environ.get('MINIPROGRAM_APPID')
    if not app_secret:
        app_secret = os.environ.get('MINIPROGRAM_SECRET')

    return app_id, app_secret


def get_tenant_wechat_gzh_config(tenant_id=None):
    """获取租户的微信公众号配置"""
    from app.services.tenant_config_service import TenantConfigService
    from app.models.tenant_config import ConfigTypes
    from flask import g, has_request_context

    if tenant_id is None:
        # 只有在请求上下文中才尝试从g获取tenant_id
        if has_request_context():
            tenant_id = getattr(g, 'tenant_id', 1)
        else:
            tenant_id = 1  # 默认使用租户1

    app_id = TenantConfigService.get_config(tenant_id, ConfigTypes.WECHAT_GZH, 'app_id')
    app_secret = TenantConfigService.get_config(tenant_id, ConfigTypes.WECHAT_GZH, 'app_secret')

    # 如果租户配置不存在，使用环境变量兜底
    if not app_id:
        app_id = os.environ.get('GMINIPROGRAM_APPID')
    if not app_secret:
        app_secret = os.environ.get('GMINIPROGRAM_SECRET')

    return app_id, app_secret


@login_bp.route('/login', methods=['POST'])
def login():
    data = request.get_json()
    code = data.get('code')
    app_id = data.get('app_id', 'wx1830687798261185')
    if not code and not app_id:
        return jsonify({"code": 0, "msg": "缺少参数"})

    # 获取租户
    tenant = Tenant.query.filter_by(app_id=app_id).first()
    if not tenant:
        return jsonify({"code": 0, "msg": "租户不存在"})

    # 获取租户的微信小程序配置
    wx_app_id, wx_app_secret = get_tenant_wechat_mp_config(tenant.id)

    if not wx_app_id or not wx_app_secret:
        return jsonify({"code": 0, "msg": "租户微信小程序配置不完整"})

    # 请求微信API获取openid
    wx_api_url = f"https://api.weixin.qq.com/sns/jscode2session?appid={wx_app_id}&secret={wx_app_secret}&js_code={code}&grant_type=authorization_code"
    try:
        wx_response = requests.get(wx_api_url)
        wx_data = wx_response.json()

        if 'errcode' in wx_data and wx_data['errcode'] != 0:
            return jsonify({"code": 0, "msg": f"微信登录失败: {wx_data.get('errmsg', '')}"})

        openid = wx_data.get('openid')
        unionid = wx_data.get('unionid')

        user = None
        if unionid:
            user = User.query.filter_by(unionid=unionid).first()

        if not user and openid:
            user = User.query.filter_by(mp_open_id=openid).first()

        if user:
            user.mp_open_id = openid
            if unionid:
                user.unionid = unionid

            if tenant:
                user.tenant_id = tenant.id
            user.app_id = wx_app_id  # 使用动态获取的app_id
            db.session.commit()
        else:
            # 创建新用户，设置初始使用次数为4
            user = User(
                nick_name='微信用户',
                mp_open_id=openid,
                unionid=unionid,
                app_id=wx_app_id,  # 使用动态获取的app_id
                tenant_id=tenant.id if tenant else None,
                usage_count=4  # 首次使用设置为4次
            )
            db.session.add(user)
            db.session.commit()

        # 创建包含租户信息的JWT token
        token = create_access_token(
            identity=user.user_id,
            additional_claims={
                'tenant_id': user.tenant_id,
                'user_id': user.user_id,
                'role': user.role if hasattr(user, 'role') else 'user'
            }
        )
        return jsonify({
            "code": 1,
            "msg": "登录成功",
            "data": {
                "userInfo": user.to_dict(),
                "token": token
            }
        })

    except Exception as e:
        current_app.logger.error(f"登录错误: {str(e)}")
        return jsonify({"code": 0, "msg": f"服务器错误: {str(e)}"})


def wechat_callback():
    data = request.get_json()
    code = data.get('code')
    tenant_id = data.get('tenant_id')  # 获取app_id用于确定租户
    tenant = Tenant.query.get(tenant_id)  # 确保租户存在
    if not tenant and not code:
        return "缺少参数", 400
    gzh_app_id, gzh_app_secret = get_tenant_wechat_gzh_config(tenant.id)
    print("获取到的微信公众号配置:", gzh_app_id, gzh_app_secret)
    if not gzh_app_id or not gzh_app_secret:
        return jsonify({"code": 0, "msg": "租户微信公众号配置不完整"})

    url = (
        f"https://api.weixin.qq.com/sns/oauth2/access_token"
        f"?appid={gzh_app_id}&secret={gzh_app_secret}&code={code}&grant_type=authorization_code"
    )
    try:
        response = requests.get(url)
        data = response.json()
        print("微信登录返回数据:", data)
        if 'errcode' in data:
            return jsonify({"code": 0, "msg": f"获取失败: {data.get('errmsg')}"})
        openid = data.get("openid")
        access_token = data.get("access_token")
        unionid = data.get("unionid")

        if not openid:
            return jsonify({"code": 0, "msg": "获取openid失败"})

        # 默认信息
        nickname = "微信用户"
        avatar_url = ""
        gender = 0
        city = "未知"
        province = "未知"
        country = "未知"

        # 尝试获取用户详细信息
        try:
            user_info_url = (
                f"https://api.weixin.qq.com/sns/userinfo?access_token={access_token}&openid={openid}&lang=zh_CN"
            )
            user_info_resp = requests.get(user_info_url)
            user_info_resp.encoding = 'utf-8'  # 明确指定编码
            user_info = user_info_resp.json()
            if 'errcode' not in user_info:
                # 原始微信昵称
                nickname = user_info.get("nickname", nickname)
                avatar_url = user_info.get("headimgurl", "")
                gender = user_info.get("sex", 0)
                city = user_info.get("city", city)
                province = user_info.get("province", province)
                country = user_info.get("country", country)
            else:
                print("获取用户信息失败:", user_info.get("errmsg"))
        except Exception as e:
            print("获取用户信息异常:", str(e))

        user = None
        if unionid:
            user = User.query.filter_by(unionid=unionid).first()

        if not user and openid:
            user = User.query.filter_by(gzh_open_id=openid).first()

        if user:
            user.gzh_open_id = openid
            if unionid:
                user.unionid = unionid
            user.app_id = gzh_app_id  # 使用动态获取的app_id
            # 更新租户ID
            if tenant:
                user.tenant_id = tenant.id
            db.session.commit()
        else:
            user = User(
                nick_name=nickname,
                gzh_open_id=openid,
                avatar_url=avatar_url,
                gender=gender,
                unionid=unionid,
                app_id=gzh_app_id,  # 使用动态获取的app_id
                tenant_id=tenant.id if tenant else None,
                usage_count=4
            )
            db.session.add(user)
            db.session.commit()

        # 创建包含租户信息的JWT token
        token = create_access_token(
            identity=user.user_id,
            additional_claims={
                'tenant_id': user.tenant_id,
                'user_id': user.user_id,
                'role': user.role if hasattr(user, 'role') else 'user'
            }
        )

        print("登录成功，生成的token:", token)
        return jsonify({
            "code": 1,
            "msg": "登录成功",
            "data": {
                "userInfo": user.to_dict(),
                "token": token
            }
        })
    except Exception as e:
        print("登录异常:", str(e))
        return jsonify({"code": 0, "msg": f"服务器错误: {str(e)}"})


def wx_signature():
    data = request.get_json()
    url = data.get('url')
    app_id = data.get('app_id')  # 获取app_id用于确定租户

    if not url:
        return jsonify({'code': 0, 'msg': '缺少url'})

    # 获取租户
    tenant = None
    if app_id:
        tenant = Tenant.query.filter_by(app_id=app_id).first()

    # 获取租户的微信公众号配置
    tenant_id = tenant.id if tenant else 1
    gzh_app_id, gzh_app_secret = get_tenant_wechat_gzh_config(tenant_id)

    if not gzh_app_id or not gzh_app_secret:
        return jsonify({'code': 0, 'msg': '租户微信公众号配置不完整'})

    # 获取access_token
    token_res = requests.get(
        f'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={gzh_app_id}&secret={gzh_app_secret}')
    access_token = token_res.json().get('access_token')

    # 获取jsapi_ticket
    ticket_res = requests.get(
        f'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={access_token}&type=jsapi')
    jsapi_ticket = ticket_res.json().get('ticket')

    nonceStr = ''.join(random.choices(string.ascii_letters + string.digits, k=16))
    timestamp = int(time.time())

    s = f'jsapi_ticket={jsapi_ticket}&noncestr={nonceStr}&timestamp={timestamp}&url={url}'
    signature = hashlib.sha1(s.encode('utf-8')).hexdigest()

    return jsonify({
        'code': 1,
        'data': {
            'appId': gzh_app_id,  # 使用动态获取的app_id
            'timestamp': timestamp,
            'nonceStr': nonceStr,
            'signature': signature
        }
    })


def generate_url_link():
    """生成小程序URL链接"""
    # 获取租户的微信小程序配置
    wx_app_id, wx_app_secret = get_tenant_wechat_mp_config()

    if not wx_app_id or not wx_app_secret:
        return jsonify({'code': 0, 'msg': '租户微信小程序配置不完整'})

    # Step 1: 获取 access_token
    token_res = requests.get(
        f'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={wx_app_id}&secret={wx_app_secret}')
    token_json = token_res.json()
    access_token = token_json.get('access_token')
    if not access_token:
        return jsonify({'code': 0, 'msg': f'获取 access_token 失败: {token_json}'})

    # Step 2: 请求生成 url_link
    api_url = f'https://api.weixin.qq.com/wxa/generate_urllink?access_token={access_token}'
    payload = {
        "path": "pages/index/index",  # 小程序页面路径
        "expire_type": 1,  # 设置链接失效
        "expire_interval": 1,  # 失效时间，单位：天（最多30）
        "env_version": "develop"  # 可选：release / trial / develop
    }

    res = requests.post(api_url, json=payload)
    res_json = res.json()
    if res_json.get('errcode') == 0:
        return jsonify({'code': 1, 'url_link': res_json.get('url_link')})
    else:
        return jsonify({'code': 0, 'msg': f'生成失败: {res_json}'})
